package igor.lakienko.ru.generation.quotes.service;

import igor.lakienko.ru.generation.quotes.dto.CryptocurrencyDto;
import igor.lakienko.ru.generation.quotes.dto.CurrencyDto;
import igor.lakienko.ru.generation.quotes.dto.PreciousMetalDto;
import igor.lakienko.ru.generation.quotes.dto.StockDto;
import igor.lakienko.ru.generation.quotes.enums.TypeSecurities;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.lang.reflect.Field;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;

@ExtendWith(MockitoExtension.class)
class CompositeServiceTest {

    @Mock
    PreciousMetalService preciousMetalService;

    @Mock
    CurrencyService currencyService;

    @Mock
    CryptocurrencyService cryptocurrencyService;

    @Mock
    StockService stockService;

    @InjectMocks
    CompositeQuoteService compositeService;


    @BeforeEach
    void setUp() {
        getSizeBatchField();
    }

//    @Test
    void whenGetQuote_thenSuccessRandomQuote() {
        //given
        given(preciousMetalService.getMetal()).willReturn(PreciousMetalDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.PRECIOUS_METAL)
                .build());
        given(currencyService.getCurrency()).willReturn(CurrencyDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.CURRENCY)
                .build());
        given(cryptocurrencyService.getCryptocurrency()).willReturn(CryptocurrencyDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.CRYPTOCURRENCY)
                .build());
        given(stockService.getStock()).willReturn(StockDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.STOCK)
                .build());

        //when
        String quote = compositeService.getQuote();

        //then
        assertThat(quote).isNotNull();
    }

    @Test
    void whenGetQuotes_thenSuccessRandomQuotes() {
        //given
        given(preciousMetalService.getMetals()).willReturn(List.of(PreciousMetalDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.PRECIOUS_METAL)
                .build()));
        given(currencyService.getCurrencies()).willReturn(List.of(CurrencyDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.CURRENCY)
                .build()));
        given(cryptocurrencyService.getCryptocurrencies()).willReturn(List.of(CryptocurrencyDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.CRYPTOCURRENCY)
                .build()));
        given(stockService.getStocks()).willReturn(List.of(StockDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.STOCK)
                .build()));

        //when
        String quote = compositeService.getQuotes();

        //then
        assertThat(quote).isNotNull();
    }

    @SneakyThrows
    private void getSizeBatchField() {
        Field quoteSizeBatch = compositeService.getClass().getDeclaredField("isQuoteEnabled");
        quoteSizeBatch.setAccessible(true);
        quoteSizeBatch.set(compositeService, true);
    }

}